#ifndef FHE_CORE_INODEDESC_H
#define FHE_CORE_INODEDESC_H

#include <fhe/core/IFuncDesc.h>
#include <fhe/core/IVarDesc.h>
#include <fhe/core/INodeInterface.h>
#include <map>

namespace fhe
{
  namespace core
  {
    class FHE_API INodeDesc : public boost::noncopyable
    {
    public:
      typedef boost::shared_ptr< INodeDesc > Ptr;
      
      INodeDesc();
      virtual ~INodeDesc();
      
      std::string module() const;
      void setModule( const std::string& module );
      
      std::string name() const;
      void setName( const std::string& name );
      
      void setParent( const std::string& module, const std::string& name );
      
      typedef std::map< std::string, IFuncDesc::Ptr >::const_iterator FuncIterator;
      void addFunc( const IFuncDesc::Ptr& func );
      bool hasFunc( const std::string& name ) const;
      IFuncDesc::Ptr getFunc( const std::string& name ) const;
      FuncIterator funcsBegin() const;
      FuncIterator funcsEnd() const;
      
      typedef std::map< std::string, IVarDesc::Ptr >::const_iterator VarIterator;
      void addVar( const IVarDesc::Ptr& var );
      bool hasVar( const std::string& name ) const;
      IVarDesc::Ptr getVar( const std::string& name ) const;
      VarIterator varsBegin() const;
      VarIterator varsEnd() const;
      
      typedef std::map< std::string, std::pair< std::string, std::string > >::const_iterator NodeInterfaceIterator;
      void addNodeInterface( const std::string& interfaceModule, const std::string& interfaceName );
      bool hasNodeInterface( const std::string& name ) const;
      std::pair< std::string, std::string > getNodeInterface( const std::string& name ) const;
      NodeInterfaceIterator nodeInterfacesBegin() const;
      NodeInterfaceIterator nodeInterfacesEnd() const;
      
      virtual void build( Node* node ) const;
      virtual Node* build() const = 0;
      
      bool resolved() const;
      void resolve();
      
    private:
      std::string module_;
      std::string name_;
      std::string parentModule_;
      std::string parentName_;
      std::map< std::string, IFuncDesc::Ptr > funcs_;
      std::map< std::string, IVarDesc::Ptr > vars_;
      std::map< std::string, std::pair< std::string, std::string > > nodeInterfaces_;
    };
    
  }
}

#endif
